classdef GIFunction < handle

  properties
    giInfo__ = 0
    ismethod__
    name__
  end
  
  methods

    function varargout = subsref(f, S, noutrequested)
      if nargin < 3
        noutrequested = nargout;
        indirectReturn = false;
      else
        if nargout > 1, error 'Too many outputs for indirect GIFunction call return', end
        indirectReturn = true;
      end
      if length(S) > 1, error 'Too many subscripts for GIFunction', end
      switch S.type
        case '.'
          if noutrequested > 1, error 'Incorrect number of outputs for GIFunction property', end
          switch S.subs
            case 'ismethod__'
              ret = f.ismethod__;
            case 'name__'
              ret = f.name__;
            case 'handle__'
              ret = f.getHandle();
            otherwise
              error 'Unsupported GIFunction property'
          end
          if indirectReturn, varargout{1} = { ret };
          else varargout{1} = ret; end
        case '()'
          ret = glib.g_irepository_matlab_invoke(f.giInfo__, S.subs);
          nret = length(ret);
          if noutrequested > nret, error 'Too many outputs for function', end
          nout = min(max(noutrequested,1),nret);
          if indirectReturn
            varargout{1} = ret(1:nout);
          else
            varargout(1:nout) = ret(1:nout);
          end
        otherwise
          error 'Unsupported subscript for GIFunction'
      end
    end

    function h = getHandle(f)
      function varargout = doCall(varargin)
        ret = glib.g_irepository_matlab_invoke(f.giInfo__, varargin);
        nret = length(ret);
        if nargout > nret, error 'Too many outputs for function', end
        nout = min(max(nargout,1),nret);
        varargout(1:nout) = ret(1:nout);
      end
      h = @doCall;
    end

    function h = getClosure(f, obj)
      function varargout = doClosureCall(varargin)
        ret = glib.g_irepository_matlab_invoke(f.giInfo__, { obj varargin{:} });
        nret = length(ret);
        if nargout > nret, error 'Too many outputs for function', end
        nout = min(max(nargout,1),nret);
        varargout(1:nout) = ret(1:nout);
      end
      h = @doClosureCall;
    end

    function f = GIFunction(giInfo, ismethod, name)
      f.giInfo__ = giInfo;
      f.ismethod__ = ismethod;
      f.name__ = name;
    end
    
    function s = char(f)
      s = sprintf('[GIFunction: %s]', f.name__);
    end
    
    function disp(f)
      disp(char(f));
    end
    
    function delete(f)
      glib.g_irepository_matlab_release_info(f.giInfo__);
    end

  end % methods
  
end
